
function TroopMatch() {
    this.players = {        // 全部玩家
        // uid : {team, name, headpic}
    };

    this.uids = [];         // 全部玩家Id

    this.rank = [];         // 排行榜
    this.reward = [];       // 排行榜奖励
    this.rewardWeek = 0;    // 排行榜奖励周

    this.lose = {           // 最近一次失败对手
    };

    this.log = null;        // 最近战报日志
}

TroopMatch.create = function() {

    var troopMatch = {
        _id: 'troop_match', 
        rank : [],
        reward : [],
        reward_week : 0,
    };

    gDBWorld.insert(troopMatch, function(err, result){});
};

TroopMatch.prototype = {
    init : function(callback) {
        gDBWorld.findOne({_id : 'troop_match'}, {}, function(err, doc){
            if( doc ) {
                this.rank = doc.rank;
                this.reward = doc.reward;
                this.rewardWeek = doc.reward_week;
                this._init(callback);
            }else{
                callback && callback(false);
            }
        }.bind(this));
    },

    _init : function(callback) {
        // 插入NPC
        this.players[1000000] = {
            name:'刘安', 
            headpic:'', 
            team:{
                0:1, 1:2, 2:3, 3:4, 4:5, 5:6, 6:7, 7:0, 8:0, 9:0
            }
        };

        this.uids.push(1000000);

        callback && callback(true);
    },

    save : function(callback) {
        var troopMatch = {
            _id: 'troop_match', 
            rank: this.rank,
            reward: this.reward,
            reward_week: this.rewardWeek,
        };

        gDBWorld.save(troopMatch, function(err, result){
            if( err ) {
                ERROR(util.format('SAVE TROOP_MATCH: %j %j', err, troopMatch));
                callback && callback(false);
            }else {
                callback && callback(true);
            }
        });
    },

    getReward : function(uid) {
        // 先更新奖励
        var passedDay = common.getDayPassed('2013-12-16'); // 星期一
        var week = Math.ceil(passedDay/7);
        if( week != this.rewardWeek ) {
            this.reward = [];
            for( var i=0; i<this.rank.length; i++ ) {
                this.reward.push({uid: this.rank[i].uid, reward:0});
            }
            this.rank = [];
            this.rewardWeek = week;

            this.save();
        }


        for( var i=0; i<this.reward.length; i++ ) {
            var rewardObj = this.reward[i];
            if( (rewardObj.uid == uid)  && !rewardObj.reward ) {
                rewardObj.reward = 1;
                this.save();
                return (i+1);
            }
        }

        return 0;
    },

    updateRank : function(uid, score, name, headpic) {
        if( score <= 0 ) return;

        var userInfo = this.players[uid];
        if( !userInfo ) {
            userInfo = {'name': name, 'headpic': headpic};
        }

        if( (this.rank.length >= 3) && (score <= this.rank[this.rank.length-1].socre) ) {
            return;
        }
        
        var exist = false;
        for( var i=0; i<this.rank.length; i++ ) {
            var rankObj = this.rank[i];
            if( rankObj.uid == uid ) {
                exist = true;
                rankObj.score = score;
                if( userInfo.name ) {
                    rankObj.name = userInfo.name;
                    rankObj.headpic = userInfo.headpic;
                }
            }
        }

        if( !exist ) {
            this.rank.push({uid:uid, score:score, name:userInfo.name, headpic:userInfo.headpic});
        }

        this.rank.sort(function(a, b){
            return b.score - a.score;
        });

        if( this.rank.length > 3 ) {
            this.rank.splice(3);
        }

        this.save();
    },

    saveTeam : function(uid, name, headpic, team) {
        if( !this.players[uid] ) {
            if( this.uids.length >= 100000 ) {
                var deleteUid = this.uids.shift(); 
                delete this.players[deleteUid];
                delete this.lose[deleteUid];
            }

            this.uids.push(uid);
        }

        this.players[uid] = {name:name, headpic:headpic, team:team};
    },

    match : function(uid) {
        var matched = [];
        var maxMatch = 10;
        if( this.uids.length <= 10 ) {
            var maxMatch = 1;
        }
        for( var i=1; i<=maxMatch; i++ ) {
            var enemyUid = this._match(uid);
            var enemyInfo = this.players[enemyUid];
            matched.push({uid:enemyUid, name:enemyInfo.name, headpic:enemyInfo.headpic});
        }

        var enemyUid = matched[matched.length-1].uid;
        
        return {'matched': matched, 'battle':this.fight(uid, enemyUid)};
    },

    _match : function(uid) {
        var index = common.randRange(0, this.uids.length-1);
        var enemyUid = this.uids[index];
        if( enemyUid == uid ) {
            if( index == 0 ) {
                index += 1;
            }else{
                index -= 1;
            }
            enemyUid = this.uids[index];
        }

        return enemyUid;
    },

    fight : function(uid, enemyUid) {
        var fighter = new Fighter();
        fighter.initWithTroopMatch(uid, this.players[uid]);
        var enemy = new Fighter();
        enemy.initWithTroopMatch(enemyUid, this.players[enemyUid]);
        
        var battleReport = fighter.fight(enemy);
        if( !battleReport.succ ) {
            this.lose[uid] = enemyUid;
        }else{
            delete this.lose[uid];
        }

        return battleReport;
    },
}

exports.get_top = function(req, res, resp) {
    var uid = req.uid;

    gTroopMatch.updateRank(uid, req.args.score, req.args.name, req.args.headpic);
    
    resp.data.reward = gTroopMatch.getReward(uid);
    resp.data.rank = gTroopMatch.rank;
    
    onReqHandled(res, resp);
}

exports.save_team = function(req, res, resp) {
    gTroopMatch.saveTeam(uid, req.args.name, req.args.headpic, req.args.team);

    onReqHandled(res, resp);
}

exports.match = function(req, res, resp) {
    var uid = req.uid;
    
    gTroopMatch.saveTeam(uid, req.args.name, req.args.headpic, req.args.team);

    var result = gTroopMatch.match(uid);
    resp.data.battle = result.battle;
    resp.data.matched = result.matched;
    resp.data.log = gTroopMatch.log;
    
    var battle = result.battle;
    if( battle.success && req.args.win >= 2 ) {
        gTroopMatch.log = [battle.atk_name, battle.def_name, req.args.win+1, uid];
    }
    
    onReqHandled(res, resp);
}

exports.retry = function(req, res, resp) {
    var uid = req.uid;
    do {
        if( !gTroopMatch.lose[uid] || !gTroopMatch.players[uid] ) {
            resp.code = 1; resp.desc = 'no lose retry'; break;
        }
        
        var enemyUid = gTroopMatch.lose[uid];
        if( !gTroopMatch.players[enemyUid] ) {
            resp.code = 1; resp.desc = 'enemy not exist'; break;
        }

        gTroopMatch.saveTeam(uid, req.args.name, req.args.headpic, req.args.team);
        resp.data.battle = gTroopMatch.fight(uid, gTroopMatch.lose[uid]);

    }while(false);
    
    onReqHandled(res, resp);
}

exports.TroopMatch = TroopMatch;
